package com.yzkj.cpjxc.business.system.exception;

import com.yzkj.cpjxc.business.constants.SysLogConstants;
import com.yzkj.cpjxc.business.domain.SysLog;
import com.yzkj.cpjxc.business.service.SysLogService;
import com.yzkj.cpjxc.business.system.interceptor.DoLog;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.remoting.caucho.HessianServiceExporter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;

/**
 * 异常处理器
 */
public class ExceptionHandler implements HandlerExceptionResolver {

	private Logger logger = Logger.getLogger(ExceptionHandler.class);

	@Autowired
	private SysLogService sysLogService;

	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
		
		if (handler instanceof HessianServiceExporter) {
			// TODO xie-qing 暂时什么都不做处理
			return null;
		}
		HandlerMethod handlerMethod = (HandlerMethod) handler;
		Method method = handlerMethod.getMethod();
	    String cnContent="";
		if (method != null) {
			SysLog sysLog = new SysLog();
			//	String opeContent = handlerMethod.getBean().getClass().getName() + "." + method.getName();//日志内容
			if (method.isAnnotationPresent(DoLog.class)) {
				DoLog doLog = method.getAnnotation(DoLog.class);
				cnContent=doLog.cnContent();
				sysLog.setOpeContent("系统异常：" +cnContent);
			} else {
				sysLog.setOpeContent("系统异常");
			}

			StringBuffer paramValues = new StringBuffer();
			Enumeration enums = request.getParameterNames();
			while (enums.hasMoreElements()) {
				Object obj = enums.nextElement();
				paramValues.append(obj).append(":");
				String vals[] = request.getParameterValues("" + obj);
				for (int i = 0; i < vals.length; i++) {
					paramValues.append(vals[i]);
					paramValues.append((i == vals.length - 1) ? ";" : ",");
				}
			}
			String allParamValue=paramValues.toString();
			// 参数过长处理
			if (paramValues.length() > 600) {
				sysLog.setParamValues(paramValues.toString().substring(0, 600));
			} else {
				sysLog.setParamValues(paramValues.toString());
			}
			sysLog.setLogType(SysLogConstants.LOG_TYPE_ERROR);//日志类型

			
			// 记录异常信息
			if (e != null) {
				StringBuffer sb=new StringBuffer();
				sb.append("操作的内容为："+cnContent);
				sb.append(" 调用: " + request.getRequestURI()+"时发生异常");
				sb.append(" 请求参数为:"+allParamValue);
				logger.error(sb.toString(), e);
				
				//异常信息
				if (StringUtils.isNotBlank(e.getMessage())) {
					if (e.getMessage().length() > 600) {
						sysLog.setExMsg(e.getMessage().toString().substring(0, 600));//
					} else {
						sysLog.setExMsg(e.getMessage());
					}
				}
				// sysLog.setExMsg(e.getMessage());//异常信息

				StringBuffer errLocation = new StringBuffer();
				List<String> list = new ArrayList<String>();
				String className = null;
				for (StackTraceElement ex : e.getStackTrace()) {
					className = ex.getClassName();
					if (StringUtils.contains(className, "org.eking")) {
						list.add(ex.getClassName() + "." + ex.getMethodName() + "(" + ex.getFileName() + ":" + ex.getLineNumber());
					}
				}
				if (list != null && list.size() > 0) {
					for (int i = 0; i < list.size(); i++) {
						errLocation.append(list.get(i));
						if (i != list.size() - 1) {
							errLocation.append("\n");
						}
					}
				}
				if (errLocation.length() > 600) {
					sysLog.setErrLocation(errLocation.toString().substring(0, 600));//
				} else {
					sysLog.setErrLocation(errLocation.toString());
				}
			}
			sysLog.setOperationTime(new Date());
			sysLog.setRequestUrl(request.getRequestURI());
			try {//执行注销操作后当前session会被销毁，所以WebUtils工具类中的getLoginUserName(request)方法会从当前请求中获取session,因为如果是被注销后无法获取，会抛出异常
				sysLog.setOperationUsername("----");//登录人
			} catch (Exception eq) {}

			logger.info(sysLog);
			try {
				sysLogService.create(sysLog);
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		return new ModelAndView("common/error/error500").addObject("exception", e);
	}

}
